<script lang="ts" setup>
import type PropsDefination from "./extends/props";
import type EmitsDefination from './extends/emits';
import type { TableLocalConfig } from './type';
import { EmptyEnum } from './type.d';
import { withDefaults, computed, ref, onMounted, watch, reactive } from "vue";
import { AddIcon, UploadIcon, DownloadIcon, SettingIcon } from 'tdesign-icons-vue-next';
import CrudManager from "./index";
import { TableProps } from "tdesign-vue-next";
import { FormType } from '@/view/compont/crud/component/formDialog/type.d'

import FormDialog from '../formDialog/index.vue'

const props = withDefaults(defineProps<PropsDefination>(), {
  columns: () => [],
});

const emits = defineEmits<EmitsDefination>();

/**
 * 组件实例
 */
const { 
  data,
  pagination,
  selectedRowKeys,
  sort,
  exportDisabled,
  dialogVisible,
  getTableLocalConfig,
  formData,
  formType,
  sumbitLoading,
  tableLoading,
  onSumbit,
  onReset,
  editBtnClick,
  infoBtnClick,
  addBtnClick,
  rehandleSelectChange,
  sortChange,
  getList,
  queryStatus
} = new CrudManager<object>(props.name, props.defalutData, emits);

const tableLocalConfig = reactive<TableLocalConfig>(getTableLocalConfig(props.name))

/**
 * 保存表格本地配置
 */
const saveTableLocalConfig = (tableCon: TableLocalConfig) => {
  localStorage.setItem(props.name, JSON.stringify(tableCon))
}

// 合并表头配置，有些表格的列配置是固定的，比如操作列
const widthDefualtColKey = ['row-select', 'action']
const allColumns = computed(() => {
  const allColumns: TableProps['columns'] = [
    {
      colKey: 'row-select',
      type: 'multiple',
      width: 50,
    },
    ...props.columns,
    { 
      colKey: 'action',
      title: '操作', 
      width: 240, 
      cell: 'action', 
      resize: { minWidth: 240, maxWidth: 240 },
      fixed: 'right'
    }
  ]
  return allColumns.map(item => {
    // 合并列宽
    if(tableLocalConfig.columnsWidth && widthDefualtColKey.indexOf(item.colKey) !== -1) {
      return {
        ...item,
        width: tableLocalConfig.columnsWidth[item.colKey] || item.width
      }
    } else {
      return item
    }
  })
})

// 获取需要插槽显示的列
const cellStr = computed(() => 
  props.columns.filter(item => item.cell).map(item => item.colKey)
)

// 显示表格列
const columnControllerVisible = ref(false)
const columnControllerConfig = computed<TableProps['columnController']>(() => ({
  placement: 'top-right',
  hideTriggerButton: true,
}));
const displayColumns = ref<TableProps['displayColumns']>([])
onMounted(() => {
  displayColumns.value = 
    tableLocalConfig?.displayColumns ?
      tableLocalConfig.displayColumns :
      allColumns.value.map(item => item.colKey)
})
// 更新显示列
watch(displayColumns, () => {
  tableLocalConfig.displayColumns = displayColumns.value
  saveTableLocalConfig(tableLocalConfig)
})
// 更新列宽
const onColumnResizeChange: TableProps['onColumnResizeChange'] = (columnsWidth) => {
  tableLocalConfig.columnsWidth = columnsWidth.columnsWidth
  saveTableLocalConfig(tableLocalConfig)
};
// 更新排序
watch(sort, () => {
  tableLocalConfig.sort = sort.value
  saveTableLocalConfig(tableLocalConfig)
}, { deep: true })
</script>

<template>
  <div class="main">
    <div class="table-action">
      <div class="btn-action">
        <t-button @click="addBtnClick" v-if="defalutData.hasOwnProperty(FormType.Add)">
          <template #icon><add-icon /></template>
          新增
        </t-button>
        <t-button theme="default" v-if="defalutData.hasOwnProperty(FormType.Add)">
          <template #icon><UploadIcon /></template>
          导入
        </t-button>
        <t-button theme="default" :disabled="exportDisabled">
          <template #icon><DownloadIcon /></template>
          导出
        </t-button>
        <t-button theme="default">
          <template #icon><DownloadIcon /></template>
          全部导出
        </t-button>
      </div>
      <div class="btn-action">
        <t-button variant="outline" theme="default" @click="columnControllerVisible = true">
          <template #icon><SettingIcon /></template>
          列配置
        </t-button>
      </div>
    </div>
    <t-enhanced-table
      row-key="id"
      :data="data"
      :columns="allColumns"
      bordered
      size="small"
      height="calc(100vh - 330px)"
      hover
      :pagination="pagination"
      v-model:displayColumns="displayColumns"
      v-model:columnControllerVisible="columnControllerVisible"
      :column-controller="columnControllerConfig"
      resizable
      @column-resize-change="onColumnResizeChange"
      :selected-row-keys="selectedRowKeys"
      @select-change="rehandleSelectChange"
      multiple-sort
      :sort="sort"
      @sort-change="sortChange"
      :loading="tableLoading"
    >
      <template
        v-for="item in cellStr"
        :key="item"
        #[item]="{ row }"
      >
        <slot :name="item" :row="row"></slot>
      </template>
      <template #action="{ row }">
        <t-button @click="infoBtnClick(row)" variant="text" theme="primary">详情</t-button>
        <t-button @click="editBtnClick(row)" variant="text" theme="primary" v-if="defalutData.hasOwnProperty(FormType.Edit)">编辑</t-button>
        <t-button @click="editBtnClick(row)" variant="text" theme="danger">删除</t-button>
      </template>
      <template #empty>
        <div class="empty" v-if="queryStatus === EmptyEnum[500]">
          <img src="/image/服务器错误.svg" alt="icon">
          服务器抽风了，请稍后再试
          <t-button @click="getList">重试看看</t-button>
        </div>
        <div class="empty" v-if="queryStatus === EmptyEnum[401]">
          <img src="/image/服务器错误.svg" alt="icon">
          登录权限过了，要看就先登录
          <t-button @click="getList">去登录</t-button>
        </div>
        <div class="empty" v-if="queryStatus === EmptyEnum[403]">
          <img src="/image/服务器错误.svg" alt="icon">
          有点数，你权限都没有
        </div>
        <div class="empty" v-if="queryStatus === EmptyEnum[200]">
          <img src="/image/服务器错误.svg" alt="icon">
          怎么啥都没有，想想自己有没有好好努力
        </div>
      </template>
    </t-enhanced-table>
    <FormDialog
      v-model:visible="dialogVisible"
      v-model:data="formData[formType]"
      :sumbitLoading="sumbitLoading"
      :header="props.name"
      :type="formType"
      :formOption="formOption"
      :rules="rules"
      @onSubmit="onSumbit"
      @onReset="onReset"
    ></FormDialog>
  </div>
</template>

<style lang="scss" scoped>
.main {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  .table-action {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
    div {
      display: flex;
      align-items: center;
      gap: 16px;
    }
  }
  .empty {
    display: flex; 
    flex-direction: column; 
    align-items: center; 
    justify-content: center; 
    height: calc(100vh - 386px);
    color: rgba(0, 0, 0, 0.26);
    gap: 16px;
    img {
      width: 48px;
      height: 48px;
    }
  }
}
</style>
